//
// Created by shiminli on 2024/1/3.
//

#include "DDRedis.h"

namespace ddoffice {
    DDRedis::DDRedis() {}
    DDRedis::~DDRedis() {
        if (this->_reply != nullptr){
            freeReplyObject(this->_reply);
            this->_reply = nullptr;
        }
        if (this->_connect != nullptr){
            redisFree(this->_connect);
            this->_connect = nullptr;
        }
        cout << "析构 DDRedis:: conn="<<_connect<<endl;
    }
    DDRedis* DDRedis::instance = nullptr;
    std::mutex DDRedis::mtx;
    DDRedis *DDRedis::getInstance() {
        if (instance == nullptr) {
            std::lock_guard<std::mutex> lock(mtx); // 加锁
            if (instance == nullptr) {
                instance = new DDRedis();
            }
        }
        return instance;
    }

    bool DDRedis::connect() {
        this->_connect = redisConnect(REDIS_HOST, REDIS_PORT);
        if (this->_connect != NULL && this->_connect->err) {
            cout << "Redis connect err: "<<this->_connect->errstr << endl;
            return REDIS_ERR;
        }
        cout << "Redis connect success" << endl;
        return auth(REDIS_PASS);
    }

    std::string DDRedis::get(const std::string &key) {
        cout << "redis get key="<<key << endl;
        this->_reply = (redisReply *) redisCommand(this->_connect, "GET %s", key.c_str());
        if (_reply == nullptr) {
            cout << "redis get value is null key="<< key << endl;
            return "";
        }
        std::string str = this->_reply->str;
        cout << "  value=" << str << endl;
        freeReplyObject(this->_reply);
        return str;
    }

    int DDRedis::set(const std::string &key, const std::string &value) {
        this->_reply = (redisReply *) redisCommand(this->_connect, "SET %s %s", key.c_str(), value.c_str());
        if (_reply == nullptr || _reply->type == REDIS_REPLY_ERROR) {
            return REDIS_REPLY_ERROR;
        }
        freeReplyObject(_reply);
        return REDIS_OK;
    }

    int DDRedis::setWithExpiration(const std::string &key, const std::string &value, int seconds) {
        if (set(key, value) == REDIS_OK) {
            this->_reply = (redisReply *) redisCommand(_connect, "EXPIRE %s %d", key.c_str(), seconds);
            if (_reply == nullptr || _reply->type == REDIS_REPLY_ERROR) {
                return REDIS_REPLY_ERROR;
            }
            freeReplyObject(_reply);
        }
        return REDIS_OK;
    }

    int DDRedis::auth(std::string password) {
        this->_reply = static_cast<redisReply *>(redisCommand(this->_connect, "auth %s", password.c_str()));
        if (_reply == nullptr || _reply->type == REDIS_REPLY_ERROR) {
            cout << "Redis auth err: "<<this->_connect->errstr << endl;
            return REDIS_ERR;
        }
        cout << "Redis auth type="<<this->_reply->type<< "  msg="<< this->_reply->str<< endl;
        freeReplyObject(this->_reply);
        return 1;
    }

}